package com.websocket.controller;

import com.alibaba.fastjson.JSON;
import com.websocket.Constants;
import com.websocket.model.HelloMessage;
import com.websocket.model.RedisWebsocketMsg;
import com.websocket.service.RedisService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.user.SimpSession;
import org.springframework.messaging.simp.user.SimpSubscription;
import org.springframework.messaging.simp.user.SimpUser;
import org.springframework.messaging.simp.user.SimpUserRegistry;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.MessageFormat;

/**
 * @author zifangsky
 * @date 2018/10/10
 * @since 1.0.0
 */
@RestController
@RequestMapping(("/wsTemplate"))
public class RedisMessageController {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Value("${spring.redis.message.topic-name}")
    private String topicName;

   @Autowired(required = false)
    private SimpMessagingTemplate messagingTemplate;

    @Autowired(required = false)
    private SimpUserRegistry userRegistry;

    @Resource(name = "redisServiceImpl")
    private RedisService redisService;

    /**
     * 给指定用户发送WebSocket消息
     */
    @PostMapping("/sendToUser")
    public String chat(HttpServletRequest request) {
        //消息接收者
        String receiver = request.getParameter("receiver");
        //消息内容
        String msg = request.getParameter("msg");

        String channel = request.getParameter("channel");

        String appk = request.getParameter("appk");

        HelloMessage resultData = new HelloMessage(MessageFormat.format("{0} say: {1}", receiver, msg));
        this.sendToUser(receiver, "/topic/" + appk + "/" + channel, JSON.toJSONString(resultData));

        return "ok";
    }

    @GetMapping("/usercount")
    public void getUserCount() {
        logger.info("用户数量 {}",userRegistry.getUserCount());
        logger.info("用户数量1 {}",userRegistry.getUsers().size());
    }



    /**
     * 给指定用户发送WebSocket消息
     */
    @PostMapping("/sendBroadcast")
    public String broadcast(HttpServletRequest request) {
        //消息内容
        String msg = request.getParameter("msg");
        String channel = request.getParameter("channel");

        String appk = request.getParameter("appk");
        HelloMessage resultData = new HelloMessage(MessageFormat.format("{0} say: {1}", "广播消息", msg));
        messagingTemplate.convertAndSend("/topic/" + appk + "/" + channel, JSON.toJSONString(resultData));
        return "ok";
    }


    /**
     * 给指定用户发送消息，并处理接收者不在线的情况
     *
     * @param receiver    消息接收者
     * @param destination 目的地
     * @param payload     消息正文
     */
    private void sendToUser(String receiver, String destination, String payload) {
        SimpUser simpUser = userRegistry.getUser(receiver);
        //如果接收者存在，则发送消息
        if (simpUser != null && StringUtils.isNoneBlank(simpUser.getName())) {
            boolean send = false;
            for (SimpSession session : simpUser.getSessions()) {
                for (SimpSubscription subscription : session.getSubscriptions()) {
                    if(destination.equals(subscription.getDestination())){
                        send =true;
                    }
                }
            }
            if(send){
                messagingTemplate.convertAndSendToUser(receiver, destination, payload);
            }else{
                logger.debug("用户目标路径不正确");
            }

        }
        //如果接收者在线，则说明接收者连接了集群的其他节点，需要通知接收者连接的那个节点发送消息
        else if (redisService.isSetMember(Constants.REDIS_WEBSOCKET_USER_SET, receiver)) {
            RedisWebsocketMsg<String> redisWebsocketMsg = new RedisWebsocketMsg<>(receiver, "WebSocketChannelEnum.CHAT.getCode()", payload);

            redisService.convertAndSend(topicName, redisWebsocketMsg);
        } else {
            logger.debug("用户不存在");
        }
    }

}
